-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Miri: non-deterministic floating point operations in foreign_items
#143906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Miri: non-deterministic floating point operations in foreign_items
#143906
Conversation
The Miri subtree was changed cc @rust-lang/miri |
There are some holes in the behaviour of some operations, because I did not know how I could efficiently handle them, I'll mark them and add some explanation. Also, |
Please create a PR for the libstd changes on their own so a libs reviewer can review it. Once that is done and synced, you can open a PR against the miri repo with the miri changes. |
In a previous PR we had both in one PR with two reviewers since we needed to go back and forth a bit. We could do that again? I think it worked well.
|
It's the same for me, I kept the commits for Miri and stdlib separate, so if I have to split it up, it's pretty straightforward. |
🤷 I'm also fine either way, it'll just be a bunch of work to port the commits to the Miri repo.
Functions where C does not give an output range shouldn't get their value clamped, I would say. |
Please don't, that file is already too big.^^ If the helpers are only needed in one file, keep them there. |
Reopening. |
You're right, but this has some consequences. For example, the The C standard for the return values of
The range of sine x is [-1, 1], but is not explicitly defined. But
I think we have 2 approaches:
|
If we run into libm implementations that can't even guarantee to return a value within the math function's output domain, tbh I would consider that downright broken and worthy of a bug report, or strong reason to just always use our If it's mostly a concern about following the specification to the letter, I think it might be worth a defect report to see if the C committee is willing to codeify the output domain. |
I would suggest a third:
|
The arcsin function likely states this not as a means of guaranteeing precision, but because the inverse sine of |
So I did @rustbot ready |
Yeah that looks good :) |
…-foreign-items, r=RalfJung Miri: non-deterministic floating point operations in `foreign_items` Part of [rust-lang/miri/rust-lang#3555](rust-lang/miri#3555 (comment)), this pr does the `foreign_items` work. Some things have changed since rust-lang#138062 and rust-lang#142514. I moved the "helpers" used for creating fixed outputs and clamping operations to their defined ranges to `math.rs`. These are now also extended to handle the floating-point operations in `foreign_items`. Tests in `miri/tests/float.rs` were changed/added. Failing tests in `std` were extracted, run under miri with `-Zmiri-many-seeds=0..1000` and changed accordingly. Double checked with `-Zmiri-many-seeds`. I noticed that the C standard doesn't specify the output ranges for all of its mathematical operations; it just specifies them as: ``` Returns The sinh functions return sinh x. ``` So I used [Wolfram|Alpha](https://www.wolframalpha.com/).
…-foreign-items, r=RalfJung Miri: non-deterministic floating point operations in `foreign_items` Part of [rust-lang/miri/rust-lang#3555](rust-lang/miri#3555 (comment)), this pr does the `foreign_items` work. Some things have changed since rust-lang#138062 and rust-lang#142514. I moved the "helpers" used for creating fixed outputs and clamping operations to their defined ranges to `math.rs`. These are now also extended to handle the floating-point operations in `foreign_items`. Tests in `miri/tests/float.rs` were changed/added. Failing tests in `std` were extracted, run under miri with `-Zmiri-many-seeds=0..1000` and changed accordingly. Double checked with `-Zmiri-many-seeds`. I noticed that the C standard doesn't specify the output ranges for all of its mathematical operations; it just specifies them as: ``` Returns The sinh functions return sinh x. ``` So I used [Wolfram|Alpha](https://www.wolframalpha.com/).
Rollup of 8 pull requests Successful merges: - #142454 (Add modern AVR mcus like avr128db28 and attiny3224) - #142924 (tidy: move rustdoc js stuff into a tidy extra check) - #143373 (Unquerify maybe_unused_trait_imports.) - #143906 (Miri: non-deterministic floating point operations in `foreign_items`) - #144082 (tests: cover more `exported_private_dependencies` cases) - #144126 (Fix empty target_config in apply_rust_config bootstrap) - #144164 ( opt-dist: add an option for setting path to stage0 root) - #144265 (Dont ICE on copy error being suppressed due to overflow) r? `@ghost` `@rustbot` modify labels: rollup
That sounds reasonable to me (but you have some f32 tests that currently use 1e-4). |
I'll set them all to 1e-4 then. |
I'll edit the last commit with --keep-base. |
a3e124f
to
4a60945
Compare
Hi, @tgross35, would you like to look at the last commit? There are a few more stdlib changes now. Changes from |
This is not setting all the f32 ones to 1e-4 (take a look at the diff). Not that I mind.^^ |
@@ -754,7 +754,7 @@ impl f64 { | |||
/// // asin(sin(pi/2)) | |||
/// let abs_difference = (f.sin().asin() - std::f64::consts::FRAC_PI_2).abs(); | |||
/// | |||
/// assert!(abs_difference < 1e-7); | |||
/// assert!(abs_difference < 1e-5); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This failed because of the double operations, but it's weird this one is so unprecise when running under miri, while others like cos
and tan
are not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried 1000 seeds and 1e-7 always worked. Why did you reduce to 1e-5?
(1e-8 failed quickly.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's weird this one is so unprecise when running under miri, while others like cos and tan are not.
asin
seems to be quite sensitive around input 1, which is what we are using here.
And yeah, looking at WA, its derivative explodes towards 1: https://www.wolframalpha.com/input?i2d=true&i=D%5Basin%5C%2840%29x%5C%2841%29%2Cx%5D.
In contrast, we are evaluating acos
at around 0.7, where its derivative is much lower.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should change the test to an area where asin is more stable -- like pi/4, which the other 2 tests are already using?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commented this on the wrong test, but you're last 2 replies apply to that test as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but you did change this one to 1e-5... why?
Yeah, just noticed. :) @rustbot ready |
4a60945
to
ba59bff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1e-5 didn't work for f32, right? Is there just a single test that is the culprit, or is it a bunch of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asinh
failed, but it's getting confusing having 3 different constants for these tests, so I wanted to unify them to one. Side note: a single f32 test has 1e-3.
Maybe if we change that test as well, I can change them back to their limits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know what you and @tgross35 prefer. Having a single constant that works for them all, or individual limits, or something else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense that operations which are direct wrappers around a libm functions, like sin
, expect higher precision than things like asinh
. So I'd say optimize for minimizing the diff here.
And yeah, please change all the asin
tests to use FRAC_PI_4 to avoid instability around asin(1)
.
@@ -1067,7 +1067,7 @@ impl f32 { | |||
/// | |||
/// let abs_difference = (f - x).abs(); | |||
/// | |||
/// assert!(abs_difference <= 1e-7); | |||
/// assert!(abs_difference <= 1e-4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's this one that failed, not the one I commented here https://github.com/rust-lang/rust/pull/143906/files#r2225770166
Maybe we should change the test to an area where asin is more stable -- like pi/4, which the other 2 tests are already using?
Agreed.
Part of rust-lang/miri/#3555, this pr does the
foreign_items
work.Some things have changed since #138062 and #142514. I moved the "helpers" used for creating fixed outputs and clamping operations to their defined ranges to
math.rs
. These are now also extended to handle the floating-point operations inforeign_items
. Tests inmiri/tests/float.rs
were changed/added.Failing tests in
std
were extracted, run under miri with-Zmiri-many-seeds=0..1000
and changed accordingly. Double checked with-Zmiri-many-seeds
.I noticed that the C standard doesn't specify the output ranges for all of its mathematical operations; it just specifies them as:
So I used Wolfram|Alpha.